<?php

// get_net.php
// Michael Baker
// 2010.07
//
// get nodetree diagram PNG data using Graphviz

define("IN_MDM", true );
require_once( '../includes/all.php' );

function get_style_str( $styles, $class_arr )
{
  $keys = array();
  
  foreach ( $class_arr as $class )
  {
    $s_arr = $styles[ $class ];
    foreach ( $s_arr as $arr )
    {
      $key = $arr[ 0 ];
    
      if ( !array_key_exists( $key, $keys ) )
        $keys[ $key ] = array();
      
      for ( $i = 1; $i < count($arr); $i++ )
        $keys[ $key ][] = $arr[ $i ];
    }
  }
  
  $str_arr = array();
  foreach ( $keys as $key => $value_arr )
  {
    $value_arr2 = array_unique($value_arr);
    $values = implode(",", $value_arr2);
    $str_arr[] = "$key=\"$values\"";
  }
  
  return implode(", ", $str_arr);
}

$styles1 = array(
  "MA" => array(
    array( "style", "solid", "filled" ),
    array( "fillcolor", "gray90" )
  ),
  
  "MP" => array(
    array( "style", "dashed", "filled" ),
    array( "fillcolor", "gray90" )
  ),
  
  "ORPHAN" => array(
    array( "color", "red" )
  ),
  
  "NONORPHAN" => array(
    array( "color", "black" )
  ),
  
  "USED" => array(
    array( "style", "solid" )
  ),
  
  "UNUSED" => array(
    array( "style", "dotted" )
  ),
  
  "GLOBAL" => array(
    array( "shape", "ellipse" ),
    array( "fontsize", "14" ),
    array( "len", "1.5" )
  )
);

$node = $_GET["id"];

$str = "digraph {";
$str .= "\n\tgraph [bgcolor=transparent];";
$str .= "\n\tsize=\"9,9\";";
$str .= "\n\tedge [arrowhead=normal];";

/* Retrieve initial and final IDs for all nodes that belong to any nodecouple */
$dbase->execute( "SELECT initial_id, final_id, category_id, db_flag, id FROM NodeCouple" );
$nc_rs = $dbase->fetchall();

$colormap = array();
$nodes = array();
$map = array();

foreach ( $nc_rs as $row ) {
  $init = $row[ 0 ];
  $fin  = $row[ 1 ];
  $cat  = $row[ 2 ];
  
  if ( !array_key_exists( $cat, $colormap ) )
  {
    // here we assume that every category has a mapcolor (ie no exception will be thrown)
    $mc = $dbase->get_thresholding_mapcolor($cat);
    if ( $mc ) 
      $colormap[ $cat ] = $mc;
  }
  
  if ( !in_array( $init, $nodes ) )
    $nodes[] = $init;
  if ( !in_array( $fin, $nodes ) ) 
    $nodes[] = $fin;
}

/* now retrieve ALL the nodes */
$dbase->execute( "SELECT id, title_l, has_db FROM Node" );
$n_rs = $dbase->fetchall();

foreach ( $n_rs as $row ) {
  $id     = $row[ 0 ];
  $title  = $row[ 1 ];
  $has_db = $row[ 2 ];
  
  // if it hasn't already been added to $nodes at this point, it belongs to no nodecouple (orphan)
  $orphType  = (in_array($id, $nodes) ? "NONORPHAN" : "ORPHAN");
  $nodeType  = ($has_db ? "MA" : "MP");
  
  $cond = ( $node && ( $id == $node ) );
  $inserted = $cond ? true : false;
  if ( $cond )
  {
    // add the definition of the specified node: "TITLE" [style stuff] into the file
    $str .= "\n\t\"$title\" [" . get_style_str( $styles1, array($nodeType, $orphType, "GLOBAL") ) . "];";
  }
  
  $map[ $id ] = array( $title, $has_db, $inserted );
}

/* Now go thorugh the nodecouples */
foreach ( $nc_rs as $row ) {
  $id   = $row[ 4 ];
  
  $conn = count($dbase->search_for_workflows($id));
  
  $init = $row[ 0 ];
  $fin  = $row[ 1 ];
  $cat  = $row[ 2 ];
  $db   = $row[ 3 ];
  
  $init_info = $map[ $init ];
  $fin_info  = $map[ $fin ];
  
  $init_str  = $init_info[ 0 ];
  $fin_str   = $fin_info[ 0 ];  
  $init_hdb  = $init_info[ 1 ];
  $fin_hdb   = $fin_info[ 1 ];
  $init_pres = $init_info[ 2 ];
  $fin_pres  = $fin_info[ 2 ];
  
  if ( !$node || ( ($init == $node) || ($fin == $node) ) ) {
    $cond1 = ( $node && ($init == $node) );
    $cond2 = ( $node && ($fin  == $node) );
    
    // If the initial or final node definitions are not yet present, add these in
    if ( !$init_pres ) {
      $nodeType = ($init_hdb ? "MA" : "MP");
      $str .= "\n\t\"$init_str\" [" . get_style_str( $styles1, array($nodeType, "GLOBAL") ) . "];";
      $map[$init][2] = true;
    }
    
    if ( !$fin_pres ) {
      $nodeType = ($fin_hdb ? "MA" : "MP");
      $str .= "\n\t\"$fin_str\" [" . get_style_str( $styles1, array($nodeType, "GLOBAL") ) . "];";
      $map[$fin][2] = true;
    }
    
    $linkType = ($conn ? "USED" : "UNUSED");

    $append = ($db) ? "\"$fin_str\" -> \"$init_str\"" : "\"$init_str\" -> \"$fin_str\"";
    $append .= " [color=" . ( array_key_exists($cat, $colormap) ? $colormap[$cat] : COLOR_UNKNOWN_CLASS ) . ", " . get_style_str( $styles1, array($linkType, "GLOBAL") ) . "];";

    $str .= "\n\t" . $append;
  }
  
}

foreach ( $map as $id => $arr ) {
  if ( !$node ) {
    $title = $arr[ 0 ];
    $has_db = $arr[ 1 ];
    $pres = $arr[ 2 ];
    
    if ( $pres ) continue;
    
    $str .= "\n\t \"$title\" [" . get_style_str( $styles1, array($nodeType, "GLOBAL") ) . "];";
  }
} 

$str .= "\n\toverlap=scale;";
$str .= "\n\tsplines=true;";
$str .= "\n}";

$tmpfname = tempnam("", "GV");
$tmpfname2 = tempnam("", "GVO");

$handle = fopen($tmpfname, "w");
fwrite($handle, $str);
fclose($handle);

exec("/usr/bin/dot -Tpng -Gepsilon=0.00001 $tmpfname -o $tmpfname2");
$handle = fopen($tmpfname2, "r");
$c = fread($handle, filesize($tmpfname2));
fclose($handle);

header( "Content-Type: image/png" );
echo $c;

?>